package org.datascooter.inface;

import java.math.BigDecimal;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import org.datascooter.bundle.EntityBundle;
import org.datascooter.cache.SimpleSnipCashe;
import org.datascooter.exception.EntityNotMappedException;
import org.datascooter.exception.SnipManagerException;
import org.datascooter.generator.IdManager;
import org.datascooter.impl.DataSnip;
import org.datascooter.impl.InstanceManager;
import org.datascooter.impl.Snip;
import org.datascooter.utils.policy.Function;
import org.datascooter.utils.policy.ReferencePolicy;
import org.datascooter.utils.policy.SnipPolicy;
import org.datascooter.utils.policy.SnipType;
import org.datascooter.utils.policy.TableValidationPolicy;

/**
 * This interface is purposed for creation a wrapper for an ISnipManager for minimize efforts to use it for developers
 * 
 * @author nemo
 */
public interface IDataManager {

	/**
	 * Returns current date of snipmanager it may be usefull where you are use a remote snipManager
	 * 
	 * @return Date
	 */
	public Date getCurrentDate();

	/**
	 * Main wrapper for a snipManager method when data must be returrned from it
	 * 
	 * @param dataSnip
	 * @return Snip
	 */
	public Snip retrieve(DataSnip dataSnip);

	public Snip retrieve(Snip snip);

	/**
	 * Main wrapper for a snipManager method when data must not be returrned from it only a number with information about success
	 * 
	 * @param dataSnip
	 */
	public void execute(DataSnip dataSnip);

	public void execute(Snip snip);

	public void executeAs(Snip snip, SnipType newType);

	/**
	 * Creates new table for entity storage
	 * 
	 * @param obj
	 */
	public void create(Object obj);

	/**
	 * Drops table for a entity
	 * 
	 * @param obj
	 */
	public void drop(Object obj);

	/**
	 * Count entities, param - obj - it may be entityName,entity instance or class
	 * 
	 * @param obj
	 * @return int
	 */
	public int count(Object obj);

	public int count(Object obj, String attribute, Object value);

	public double sum(Object obj, String attribute);

	public double avg(Object obj, String attribute);

	public double max(Object obj, String attribute);

	public double min(Object obj, String attribute);

	public BigDecimal function(Object obj, String attribute, Function function);

	/**
	 * Delete entities, param - obj - it may be entityName,entity instance or class
	 * 
	 * @param obj
	 */
	public void delete(Object obj);

	public void delete(Object obj, String attribute, Object value);

	public void batchDelete(List<?> objects);

	public void deleteById(Object obj, Object value);

	/**
	 * List entities, param - obj - may be entityName,entity instance or class
	 * 
	 * @param obj
	 */
	public <T> List<T> list(Object obj);

	public <T> List<T> list(Object obj, String attribute, Object value);

	public <T> List<T> list(Object obj, int fromRow, int fetchSize);

	public <T> List<T> list(Object obj, String attribute, Object value, int fromRow, int fetchSize);

	public <T> List<T> listCross(Class<T> clazz, String crossEntityName, Object referenceEntity);

	public <T> List<T> listReferences(Class<T> clazz, Object caller);

	/**
	 * Invoke first of entities, param - obj - may be entityName,entity instance or class
	 * 
	 * @param obj
	 */
	public <T> T first(Object obj);

	/**
	 * Invoke first of entities, param - obj - may be entityName,entity instance or class
	 * 
	 * @param obj
	 */
	public <T> T first(Object obj, String attribute, Object value);

	/**
	 * Invoke first of entities, param - obj - may be entityName,entity instance or class
	 * 
	 * @param obj
	 */
	public <T> T firstById(Object obj, Object value);

	public <T> T firstCross(Class<T> clazz, String crossEntityName, Object referenceEntity);

	public void save(Object obj);

	public void batchSave(Collection<?> input);

	public void saveOrUpdate(Object obj);

	public void saveIfNotExists(Object obj);

	public void update(Object obj);

	/**
	 * Updates - if obj is class - update attribute of all such objects, if obj is entity - update this entity by id
	 * 
	 * @param obj
	 * @param attribute
	 * @param value
	 */
	public void update(Object obj, String attribute, Object value);

	public ISnipManager getSnipManager();

	/**
	 * Verify tables - check if it exists, check it columns on existence and type
	 * 
	 * @throws SnipManagerException
	 * @throws SQLException
	 * @throws BuildClauseException
	 * @throws EntityNotMappedException
	 */
	public void verifyTables() throws SnipManagerException, SQLException, EntityNotMappedException;

	/**
	 * Verify table - check if it exists, check it columns on existence and type
	 * 
	 * @param bundle
	 */
	public void verifyTable(EntityBundle bundle);

	public boolean tableExists(Object object);

	public ISnipBuilder getBuilder();

	public String getName();

	public String getContextId();

	/**
	 * Process a data for a data set without any classes
	 * 
	 * @param entity
	 * @param fields
	 */
	public void saveSet(String entity, Object... fields);

	public Snip getSnip(DataSnip dataSnip);

	public void setSnipPolicy(SnipPolicy snipPolicy);

	public void addSnipListener(ISnipListener listener);

	public void saveOrUpdate(Snip snip);

	public void close();

	public void beginTransaction(String transactionId);

	/**
	 * Commits opened transaction which may be only one
	 * 
	 * @throws SQLException
	 */
	public void commit();

	/**
	 * Rollbacks opened transaction which may be only one
	 * 
	 * @throws SQLException
	 */
	public void rollback();

	public void requestCommit();

	public TableValidationPolicy getValidationPolicy();

	public void setValidationPolicy(TableValidationPolicy validationPolicy);

	public String getTransactionId();

	public InstanceManager getInstanceManager();

	public IBackupManager getBackup();

	public IReplicationManager getReplication();

	public void dropAll(String shemaName, boolean include, String... tableNames);

	public void clearAll(String shemaName, boolean include, String... tableNames);

	public void addBundle(EntityBundle bundle, boolean checkTable) throws EntityNotMappedException;

	public void showSQL(boolean isShow);

	public void showRetrieveSQL(boolean isShow);

	SimpleSnipCashe getSnipCashe();

	public Object retrieveData(DataSnip dataSnip);

	public SnipPolicy getSnipPolicy();

	public IdManager getIdManager();

	public void removeSnipListener(ISnipListener listener);

	DataSnip startSnip(Object obj, SnipType type);

	/**
	 * Be careful to ensure what you want - if you where send as param not string or class - changes would be applied to exactly one object
	 */
	public DataSnip snip(Object obj);

	public <T> List<T> getCross(Object container, String containerAttribute);

	public void saveCross(Object container, String containerAttribute, Object... content);

	public void removeCross(Object container, String containerAttribute, Object... content);

	public int countContent(Object container, String containerAttribute);

	public int countContainer(Class<?> containerClass, Object content, String containerAttribute);

	public DataSnip getContainerDataSnip(Class<?> containerClass, Object content, String containerAttribute);

	public <T> List<T> getContainerList(Class<T> containerClass, Object content, String containerAttribute);

	public void batchUpdate(Collection<?> input);

	public void verifyReferences(ReferencePolicy policy);

	public void deleteReferences(Object obj);

	public ISnipBuilder getBuilderInt();

	public void clearCross();

	public void provideId(Object obj);
}
